#=
    UniversalTime values are held this way:
       local_time is universal_time + UTM2LCL[1]
=#
struct UniversalTime <: AbstractClock
    value::Int4Time
end

@inline value(x::UniversalTime) = x.value
@inline Base.eltype(::Type{UniversalTime}) = Int4Time
@inline UniversalTime(x::UniversalTime) = x

@inline Clock(x::UniversalTime) = Clock(value(x))
@inline UniversalTime(x::Clock) = UniversalTime(value(x))

isuniversaltime(x::UniversalTime) = true

UniversalTime() = UniversalTime(now(Base.Dates.UTC))

Base.Dates.DateTime(x::UniversalTime) = Base.Dates.DateTime(Clock(x))
Base.Dates.Date(x::UniversalTime) = Base.Dates.Date(Clock(x))
Base.Dates.Time(x::UniversalTime) = Base.Dates.Time(Clock(x))

UniversalTime(x::Base.Dates.DateTime) = UniversalTime(Clock(x))
UniversalTime(x::Base.Dates.Date) = UniversalTime(Clock(x))

Base.string(x::UniversalTime) = string(Clock(x),"Z")
Base.show(io::IO, x::UniversalTime) = print(io, string(x))

function Base.parse(::Type{UniversalTime}, x::String)
    x = endswith(x, "Z") ? x[1:end-1] : x
    clock = parse(Clock, x)
    return UniversalTime(clock)
end

UniversalTime(x::S) where S<:AbstractString = parse(UniversalTime, x)

function UniversalTime(yr::I, mo::I=one(I), dy::I=one(I), hr::I=zero(I), mn::I=zero(I), sc::I=zero(I),
                  milli::I=zero(I), micro::I=zero(I), nano::I=zero(I)) where I<:Integer
    return UniversalTime(Clock(yr, mo, dy, hr, mn, sc, milli, micro, nano))
end
